package org.hepeng.workx.util;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;

import java.io.IOException;

/**
 * @author he peng
 */

public class StandardClassMetadata implements ClassMetadata {

    private Class<?> javaClass;
    private String className;
    private ClassReader classReader;
    private Integer access;
    private Boolean isInterface;
    private Boolean isAnnotation;
    private Boolean isAbstract;
    private Boolean isConcrete;
    private Boolean isFinal;
    private String superClassName;
    private String[] interfaceNames;

    public StandardClassMetadata(Class<?> targetClass) throws IOException {
        this(targetClass.getName());
        this.javaClass = targetClass;
    }

    public StandardClassMetadata(String className) throws IOException {
        this.classReader = new ClassReader(className);
        this.className = this.classReader.getClassName();
        this.access = this.classReader.getAccess();

        this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0);
        this.isAnnotation = ((access & Opcodes.ACC_ANNOTATION) != 0);
        this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0);
        this.isConcrete = !(this.isInterface || this.isAbstract);
        this.isFinal = ((access & Opcodes.ACC_FINAL) != 0);
        this.superClassName = this.classReader.getSuperName();
        this.interfaceNames = this.classReader.getInterfaces();
        if (ArrayUtils.isNotEmpty(this.interfaceNames)) {
            for (int i = 0 ; i < interfaceNames.length ; i++ ) {
                String classFileName = StringUtils.replace(interfaceNames[i], "/", ".");
                interfaceNames[i] = classFileName;
            }
        }
    }

    @Override
    public Class getJavaClass() {
        return this.javaClass;
    }

    @Override
    public String getClassName() {
        return this.className;
    }

    @Override
    public Boolean isInterface() {
        return this.isInterface;
    }

    @Override
    public Boolean isAnnotation() {
        return this.isAnnotation;
    }

    @Override
    public Boolean isAbstract() {
        return this.isAbstract;
    }

    @Override
    public Boolean isConcrete() {
        return this.isConcrete;
    }

    @Override
    public Boolean isFinal() {
        return this.isFinal;
    }

    @Override
    public String getSuperClassName() {
        return this.superClassName;
    }

    @Override
    public String[] getInterfaceNames() {
        return this.interfaceNames;
    }
}
